package org.example.netty.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.example.netty.config.NettyServerConfig;
import org.example.netty.handler.channel.CustomProtocolDecoder;
import org.example.netty.handler.channel.CustomProtocolEncoder;
import org.example.netty.handler.channel.HeartbeatHandler;
import org.example.netty.handler.message.MessageHandlerFactory;
import org.example.netty.handler.channel.ServerBusinessHandler;
import org.example.netty.mgt.ServerConnectionManager;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
public class NettyServer extends AbstractNettyEndpoint {
    private Thread thread;
    private NettyServerConfig config;



    public NettyServer(NettyServerConfig config, ServerConnectionManager connectionManager, MessageHandlerFactory messageHandlerFactory) {
        super(connectionManager,messageHandlerFactory,new ThreadPoolExecutor(50,200,360, TimeUnit.SECONDS
                ,new ArrayBlockingQueue<>(200),new EndpointThreadFactory("netty-server-")));
        this.config = config;

    }



    @Override
    public void start() {
        thread=new Thread(()->{
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            try {
                // start server
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .option(ChannelOption.SO_BACKLOG,128)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel channel) throws Exception {
                                channel.pipeline()
                                        .addLast("cdecoder",new CustomProtocolDecoder())//向pipeline 加入解码器
                                        .addLast("cencoder",new CustomProtocolEncoder())//向pipeline 加入编码器
                                        .addLast("heartbeat",new HeartbeatHandler(connectionManager))//向pipeline 加入心跳handler
                                        .addLast("business",new ServerBusinessHandler(connectionManager,businessThreadPool,messageHandlerFactory))//业务处理器
                                ;

                            }
                        })
                        .childOption(ChannelOption.SO_KEEPALIVE, true)
                ;

                // bind
                ChannelFuture future = bootstrap.bind(config.getPort()).sync();
                log.info("=====================  netty Server端启动成功  ===========================");
                // wait util stop
                future.channel().closeFuture().sync();
            }catch (InterruptedException interruptedException){
                log.error(">>>>>>>> nettyServer 停止服务 ");
            }
        });
        thread.setName("netty-server-thread");
        thread.setDaemon(true);
        thread.start();
    }

    @Override
    public void shutdown() {
        businessThreadPool.shutdown();
        if (thread!=null && thread.isAlive()) {
            thread.interrupt();
        }
    }


}
